<template>
  <div 
       :class="['l-draggable',{'l-draggable--active':((active || overActive)&&!readonly)},{'l-draggable--move':moveActive},{'l-draggable--click':disabled}]"
       @mousedown.stop="handleMove"
       @mouseover.stop="handleOver"
       @mouseout.stop="handleOut"
       :style="styleName">
    <div class="l-draggable__wrapper"
         ref="wrapper">
      <template v-if="(active || overActive || moveActive)&&!readonly">
        <div :style="styleLineName"
             class="l-draggable__line l-draggable__line--left"></div>
        <div :style="styleLineName"
             class="l-draggable__line l-draggable__line--top"></div>
        <div class="l-draggable__line l-draggable__line--label"
             :style="styleLabelName">{{baseLeft}},{{baseTop}}</div>
      </template>
      <template v-if="!readonly" >
        <template v-for="(item,index) in rangeList" >
            <div :class="['l-draggable__range',`l-draggable__range--${item.classname}`]"
             :key="index"
             v-if="active"
             :style="[styleRangeName,getRangeStyle(item.classname)]"
             @mousedown.stop="rangeMove($event,item.classname)"></div>
        </template>
      </template>
      <div class="l-draggable__menu"
           :style="styleMenuName"
           v-show="active || overActive">
        <slot name="menu"
              :zIndex="zIndex"
              :index="index"></slot>
      </div>
      <div class="l-draggable__item"
           ref="item">
        <slot></slot>
      </div>
      <div class="l-draggable__mask"
           v-if="!disabled && mask"></div>
    </div>
  </div>
</template>

<script>
export default {
  name: "l-draggable",
  props: {
    index: {
      type: [String, Number],
    },
    mask: {
      type: Boolean,
      default: true
    },
    scale: {
      type: Number,
      default: 1
    },
    readonly: {
      type: Boolean,
      default: false
    },
    resize: {
      type: Boolean,
      default: true
    },
    disabled: {
      type: Boolean,
      default: false
    },
    step: {
      type: Number,
      default: 1
    },
    zIndex: {
      type: [Number, String],
      default: 1
    },
    left: {
      type: Number,
      default: 0
    },
    top: {
      type: Number,
      default: 0
    },
    width: {
      type: Number
    },
    height: {
      type: Number
    },
    activeFlag:{
        type:Boolean,
        default:false
    }
  },
  data () {
    return {
      baseWidth: 0,
      baseHeight: 0,
      baseLeft: 0,
      baseTop: 0,
      children: {},
      moveActive: false,
      overActive: false,
      rangeActive: false,
      active: false,
      rangeList: [
        {
          classname: "left",
        },
        {
          classname: "right",
        },
        {
          classname: "top",
        },
        {
          classname: "bottom",
        },
        {
          classname: "top-left",
        },
        {
          classname: "top-right",
        },
        {
          classname: "bottom-left",
        },
        {
          classname: "bottom-right",
        }
      ]
    };
  },
  computed: {
    scaleVal () {
      return this.scale;
    },
    styleMenuName () {
      return {
        transformOrigin: "0 0",
        transform: `scale(${this.scaleVal})`
      };
    },
    styleLineName () {
      return {
        borderWidth: this.$getPx(this.scaleVal)
      };
    },
    styleRangeName () {
      const calc = 10 * this.scaleVal;
      return {
        width: this.$getPx(calc),
        height: this.$getPx(calc)
      };
    },
    styleLabelName () {
      return {
        fontSize: this.$getPx(18 * this.scaleVal)
      };
    },
    styleName () {
      return Object.assign(
        (() => {
          if (this.active) {
            return Object.assign(
              {
                zIndex: 9999
              },
              this.styleLineName
            );
          }
          return { zIndex: this.zIndex };
        })(),
        {
          top: this.$getPx(this.baseTop),
          left: this.$getPx(this.baseLeft),
          width: this.$getPx(this.baseWidth),
          height: this.$getPx(this.baseHeight)
        }
      );
    }
  },
  watch: {
    width (val) {
      this.baseWidth = this.$getFixed(val) || this.children.offsetWidth;

    },
    height (val) {
      this.baseHeight = this.$getFixed(val) || this.children.offsetHeight;
    },
    left (val) {
      this.baseLeft = this.$getFixed(val);
    },
    top (val) {
      this.baseTop = this.$getFixed(val);
    },
    baseWidth (val) {
      this.$refs.wrapper.style.width = this.$getPx(val);
      if (this.resize && this.children.style) {
        this.children.style.width = this.$getPx(val);
      }
    },
    baseHeight (val) {
      this.$refs.wrapper.style.height = this.$getPx(val);
      if (this.resize && this.children.style) {
        this.children.style.height = this.$getPx(val);
      }
    },
    activeFlag(val){
        this.setActive(val);
    }
  },
  mounted () {
    this.init();
  },
  methods: {
    init () {
      this.children = this.$refs.item.firstChild;
      this.baseWidth = this.$getFixed(this.width) || this.children.offsetWidth;
      this.baseHeight = this.$getFixed(this.height) || this.children.offsetHeight;
      this.baseLeft = this.$getFixed(this.left);
      this.baseTop = this.$getFixed(this.top);
    },
    setLeft (left) {
      this.baseLeft = left;
    },
    setTop (top) {
      this.baseTop = top;
    },
    getRangeStyle (postion) {
      const calc = (10 * this.scaleVal) / 2;
      let result = {};
      let list = postion.split("-");
      list.forEach(ele => {
        result[ele] = this.$getPx(-calc);
      });
      return result;
    },
    setOverActive (val) {
      this.overActive = val;
    },
    setActive (val) {
      this.active = val;
    },
    rangeMove (e, position) {
      if (this.disabled) return
      //移动的方向
      let x, y;
      //移动的位置
      let xp, yp;
      //移动的正负
      let xc, yc;
      this.rangeActive = true;
      this.handleMouseDown();
      let disX = e.clientX;
      let disY = e.clientY;
      document.onmousemove = e => {
        this.moveActive = true;
        if (position === "right") {
          x = true;
          y = false;
        } else if (position === "left") {
          x = true;
          xp = true;
          xc = true;
          y = false;
        } else if (position === "top") {
          x = false;
          y = true;
          yp = true;
          yc = true;
        } else if (position === "bottom") {
          x = false;
          y = true;
        } else if (position === "bottom-right") {
          x = true;
          y = true;
        } else if (position === "bottom-left") {
          x = true;
          y = true;
          xp = true;
          xc = true;
        } else if (position === "top-right") {
          x = true;
          y = true;
          yp = true;
          yc = true;
        } else if (position === "top-left") {
          x = true;
          y = true;
          xp = true;
          xc = true;
          yp = true;
          yc = true;
        }
        let left = e.clientX - disX;
        let top = e.clientY - disY;
        disX = e.clientX;
        disY = e.clientY;
        if (x) {
          let calc = left * this.step;
          if (xc) calc = -calc;
          if (xp) this.baseLeft = this.$getFixed(this.baseLeft - calc);
          this.baseWidth = this.$getFixed(this.baseWidth + calc);
        }
        if (y) {
          let calc = top * this.step;
          if (yc) calc = -calc;
          if (yp) this.baseTop = this.$getFixed(this.baseTop - calc);
          this.baseHeight = this.$getFixed(this.baseHeight + calc);
        }
      };
      this.handleClear()

    },
    handleOut () {
      this.overActive = false
      this.$emit("out", {
        index: this.index,
        width: this.baseWidth,
        height: this.baseHeight,
        left: this.baseLeft,
        top: this.baseTop
      });
    },
    handleOver () {
      if (this.disabled) return
      this.overActive = true
      this.$emit("over", {
        index: this.index,
        width: this.baseWidth,
        height: this.baseHeight,
        left: this.baseLeft,
        top: this.baseTop
      });
    },
    handleMove (e) {
      if (this.disabled) return
      this.active = true;
      this.handleMouseDown();
      let disX = e.clientX;
      let disY = e.clientY;
      document.onmousemove = (e) => {
        let left = e.clientX - disX;
        let top = e.clientY - disY;
        disX = e.clientX;
        disY = e.clientY;
        this.baseLeft = this.$getFixed(this.baseLeft + left * this.step);
        this.baseTop = this.$getFixed(this.baseTop + top * this.step);
      };
      this.handleClear()
    },

    handleClear () {
      document.onmouseup = () => {
        document.onmousemove = null;
        document.onmouseup = null;
        this.handleMouseUp();
      }
    },
    handleMouseDown () {
      this.moveActive = true;
      this.$emit("focus", {
        index: this.index,
        width: this.baseWidth,
        height: this.baseHeight,
        left: this.baseLeft,
        top: this.baseTop
      });
    },
    handleMouseUp () {
      this.moveActive = false;
      this.rangeActive = false;
      this.$emit("blur", {
        index: this.index,
        width: this.baseWidth,
        height: this.baseHeight,
        left: this.baseLeft,
        top: this.baseTop
      });
    }
  }
}
</script>

<style lang="less">
@import './index.less';
</style>